package org.dtrevien.tests;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.List;

import org.dtrevien.metamodel.graphviz.Graph;
import org.dtrevien.metamodel.graphviz.GraphvizModel;
import org.dtrevien.metamodel.graphviz.edgerhs.EdgeRHSNode;
import org.dtrevien.metamodel.graphviz.stmt.Stmt;
import org.dtrevien.metamodel.graphviz.stmt.impl.EdgeStmtNode;
import org.dtrevien.metamodel.graphviz.stmt.impl.NodeStmt;
import org.dtrevien.metamodel.graphviz.stmt.types.LinkType;
import org.dtrevien.metamodel.java.Attribut;
import org.dtrevien.metamodel.java.Classe;
import org.dtrevien.metamodel.java.ClasseAggregationReference;
import org.dtrevien.metamodel.java.ClasseCompositionReference;
import org.dtrevien.metamodel.java.ClasseExtendReference;
import org.dtrevien.metamodel.java.Methode;
import org.dtrevien.metamodel.java.ObjectList;
import org.dtrevien.metamodel.java.Relationship;
import org.dtrevien.metamodel.java.Value;
import org.dtrevien.metamodel.java.Visibility;
import org.dtrevien.metamodel.java.visitor.impl.GraphvizConverter;
import org.junit.Before;
import org.junit.Test;

public class GraphvizConverterTestCase {

	protected GraphvizConverter gz;
	
	@Before
	public void setUp() throws Exception {
		this.gz = new GraphvizConverter();
	}

	@Test
	public void testVisiteClasse() {
		Classe c = new Classe("Classe1", "");
		c.accept(this.gz);
		
		//results
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		NodeStmt node = (NodeStmt) stmts.get(0); 	//If GraphvizConverter works, stmts size is about 1, 
													//and class c is the only one stmt (its class is a NodeStmt)
		assertEquals(c.getName(), node.getName());
		
	}

	@Test
	public void testVisiteClasseAggregationReference() {
		Classe c = new Classe("Type", "");
		ClasseAggregationReference ca = new ClasseAggregationReference(new Classe("SType", ""), "classe1", Relationship.AGGREGATION);
		c.getAttributs().add(ca);
		c.accept(this.gz);
		
		//results
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		EdgeStmtNode edge = (EdgeStmtNode) stmts.get(1);
		
		assertEquals(edge.getNodeId().getName(), c.getName());
		assertEquals(((EdgeRHSNode)edge.getEdgeRHSs().get(0)).getNodeId().getName(), ca.getType().getName());
		assertEquals(edge.getLinkType(), LinkType.AGGREGATION);
	}

	@Test
	public void testVisiteClasseCompositionReference() {
		Classe c = new Classe("Type", "");
		ClasseCompositionReference ca = new ClasseCompositionReference(new Classe("SType", ""), "classe1", Relationship.COMPOSITION);
		c.getAttributs().add(ca);
		c.accept(this.gz);
		
		//results
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		EdgeStmtNode edge = (EdgeStmtNode) stmts.get(1);

		assertEquals(edge.getNodeId().getName(), c.getName());
		assertEquals(((EdgeRHSNode)edge.getEdgeRHSs().get(0)).getNodeId().getName(), ca.getType().getName());
		assertEquals(edge.getLinkType(), LinkType.COMPOSITION);
	}

	@Test
	public void testVisiteClasseExtendsReference() {
		Classe c = new Classe("Type", "");
		ClasseExtendReference ca = new ClasseExtendReference(new Classe("SType", ""), "classe1", Relationship.INHERITANCE, null);
		c.getAttributs().add(ca);
		c.accept(this.gz);
		
		//results
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		EdgeStmtNode edge = (EdgeStmtNode) stmts.get(1);

		assertEquals(edge.getNodeId().getName(), c.getName());
		assertEquals(((EdgeRHSNode)edge.getEdgeRHSs().get(0)).getNodeId().getName(), ca.getType().getName());
		assertEquals(edge.getLinkType(), LinkType.INHERITANCE);
	}

	@Test
	public void testVisiteValueOnClassAttribute() {
		Classe c = new Classe("Type", "");
		//Test on Class Attribute
		Value value = new Value(new Classe("SType",""), "stype", Relationship.CLASS_ATTRIBUTE, Visibility.PUBLIC);
		c.getAttributs().add(value);
		c.accept(this.gz);
		
		//result
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		NodeStmt node = (NodeStmt) stmts.get(0);

		assertEquals(node.getAttrLists().get(0).getaLists().get(0).getName(), "+stype");
		assertEquals(node.getAttrLists().get(0).getaLists().get(0).getValue(), value.getType().getName());
		
	}
	
	@Test
	public void testVisiteMethode() {
		Classe c = new Classe("Type", "");
		Methode value = new Methode(new Classe("SType",""), "getSType", Visibility.PUBLIC);
		c.getMethods().add(value);
		c.accept(this.gz);
		
		//result
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		NodeStmt node = (NodeStmt) stmts.get(0);

		assertEquals(node.getAttrLists().get(1).getaLists().get(0).getName(), "+getSType()");
		assertEquals(node.getAttrLists().get(1).getaLists().get(0).getValue(), value.getType().getName());
	}
	
	@Test
	public void testVisiteValueOnMethodParamPublic() {
		Classe c = new Classe("Type", "");
		List<Attribut> attr = new ArrayList<Attribut>();
		Value value = new Value(new Classe("String",""), "str", Relationship.METHOD_PARAM, Visibility.PUBLIC);
		attr.add(value);
		Methode m = new Methode(new Classe("SType",""), "getSType", Visibility.PUBLIC, attr);
		c.getMethods().add(m);
		c.accept(this.gz);
		
		//result
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		NodeStmt node = (NodeStmt) stmts.get(0);

		assertEquals(node.getAttrLists().get(1).getaLists().get(0).getName(), "+getSType(str : String)");
	}
	
	@Test
	public void testVisiteValueOnMethodParamPrivate() {
		Classe c = new Classe("Type", "");
		List<Attribut> attr = new ArrayList<Attribut>();
		Value value = new Value(new Classe("String",""), "str", Relationship.METHOD_PARAM, Visibility.PUBLIC);
		attr.add(value);
		Methode m = new Methode(new Classe("SType",""), "getSType", Visibility.PRIVATE, attr);
		c.getMethods().add(m);
		c.accept(this.gz);
		
		//result
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		NodeStmt node = (NodeStmt) stmts.get(0);

		assertEquals(node.getAttrLists().get(1).getaLists().get(0).getName(), "-getSType(str : String)");
	}

	@Test
	public void testVisiteValueOnRelationValue() {
		Classe c = new Classe("Type", "");
		Value value = new Value(new Classe("SType",""), "stype", Relationship.DIRECT, Visibility.PUBLIC);
		c.getAttributs().add(value);
		c.accept(this.gz);
		
		//result
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		EdgeStmtNode edge = (EdgeStmtNode) stmts.get(1);

		assertEquals(edge.getNodeId().getName(), c.getName());
		assertEquals(edge.getLinkType(), LinkType.DIRECT);
	}

	@Test
	public void testVisiteObjectList() {
		Classe c = new Classe("Type", "");
		ObjectList value = new ObjectList(new Classe("SType",""), "", Relationship.DIRECT, Visibility.PUBLIC);
		value.setCard0("0..*");
		c.getAttributs().add(value);
		c.accept(this.gz);
		
		//result
		GraphvizModel model = this.gz.getGraphvizModel();
		Graph graph = model.getGraphs().get(0); //get default created graph on index 0
		List<Stmt> stmts = graph.getStmts(); //get all statement contained by graph
		EdgeStmtNode edge = (EdgeStmtNode) stmts.get(1);

		assertEquals(edge.getNodeId().getName(), c.getName());
		assertEquals(edge.getLinkType(), LinkType.DIRECT);
		assertEquals(edge.getHeadLabel(), " 0..*");
	}

}
